package com.rizzo.analytics.services.web.controller.v1;

import com.mangofactory.swagger.annotations.ApiErrors;
import com.rizzo.analytics.domain.account.Account;
import com.rizzo.analytics.domain.quota.Quotas;
import com.rizzo.analytics.services.web.controller.v1.error.QuotasNotFoundException;
import com.rizzo.infrastructure.dark.DarkLaunch;
import com.rizzo.infrastructure.performance.Monitor;
import com.rizzo.infrastructure.quota.Quota;
import com.rizzo.infrastructure.web.validator.Save;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller("quotaController")
@RequestMapping(value = "/quota", produces = "application/json")
@Api(value = "/quota", description = "Operations about Quotas")
public class QuotasController extends RizzoController {

    private static final Logger LOGGER = LoggerFactory.getLogger(QuotasController.class);

    @Monitor(userBound = true)
    @PreAuthorize("hasRole('" + Account.ROLE_USER + "')")
    @Quota(maxCalls = 1000, expireSeconds = 86400)
    @DarkLaunch(name = "get-quotas")
    @RequestMapping(value = "/{application}", method = RequestMethod.GET, produces = "application/json")
    @ApiOperation(value = "List the quota data",
            notes = "Returns all the quotas for a given application. " +
                    "This endpoint can only be called when logged in!",
            responseClass = "com.rizzo.analytics.domain.quota.Quotas", tags = "quota")
    @ApiErrors({QuotasNotFoundException.class})
    public Quotas getQuotas(
            @PathVariable(value = "application")
            @ApiParam(name = "application", required = true,
                    value = "The full name of the application (see output of '/application' for possible values)") String application) {
        final String user = getUsernameFromContext();
        validateApplication(application);
        LOGGER.debug("Called quotas for [application : '{}'] and [user : '{}']", application, user);
        return analyticsDelegator.getQuotas(user, application, WILDCARD);
    }

    @Monitor(userBound = true)
    @PreAuthorize("hasRole('" + Account.ROLE_USER + "')")
    @Quota(maxCalls = 10000, expireSeconds = 86400)
    @DarkLaunch(name = "save-quotas")
    @RequestMapping(value = "/{application}", method = RequestMethod.POST, produces = "application/json")
    @ApiOperation(value = "Save quota data",
            notes = "Saves all the quotas for a given application. " +
                    "This endpoint can only be called when logged in!",
            responseClass = "com.rizzo.analytics.domain.quota.Quotas", tags = "quota")
    public void saveQuotas(
            @PathVariable(value = "application")
            @ApiParam(name = "application", required = true,
                    value = "The full name of the application (see output of '/application' for possible values or a new one)") String application,
            @RequestBody
            @Validated(Save.class)
            @ApiParam(name = "quotas", required = true,
                    value = "The quotas to save") Quotas quotas) {
        final String user = getUsernameFromContext();
        validateApplication(application);
        LOGGER.debug("Saving quotas for [application : '{}'] and [user : '{}']", application, user);
        analyticsDelegator.saveQuotas(user, application, quotas);
    }

    @Monitor(userBound = true)
    @PreAuthorize("hasRole('" + Account.ROLE_USER + "')")
    @Quota(maxCalls = 1000, expireSeconds = 86400)
    @DarkLaunch(name = "get-quotas-with-criteria")
    @RequestMapping(value = "/{application}/{category}", method = RequestMethod.GET, produces = "application/json")
    @ApiOperation(value = "Lists the filterable quota data",
            notes = "Returns all the quotas for a given application. " +
                    "Results from this endpoint can be filtered by category. " +
                    "This endpoint can only be called when logged in!",
            responseClass = "com.rizzo.analytics.domain.quota.Quotas", tags = "quota")
    @ApiErrors({QuotasNotFoundException.class})
    public Quotas getQuotasWithCriteria(
            @PathVariable(value = "application")
            @ApiParam(name = "application", required = true,
                    value = "The full name of the application (see output of '/application' for possible values)") String application,
            @PathVariable("category")
            @ApiParam(name = "category", required = true,
                    value = "The category or method of the rationed service (wildcards '*' are allowed but case-sensitive)") String category) {
        final String user = getUsernameFromContext();
        validateApplication(application);
        LOGGER.debug("Called quotas for [application : '{}'] and [user : '{}'] for [category : '{}']", application, user, category);
        return analyticsDelegator.getQuotas(user, application, category);
    }

}
